"""
配置管理服务器
提供配置项的管理、查询、更新等功能
"""

import os
import logging
from typing import Dict, List, Optional, Any
from fastapi import APIRouter, HTTPException, Depends, Query, Body, Path, FastAPI
from fastapi.responses import StreamingResponse, JSONResponse, HTMLResponse
from fastapi import Request
import json
from datetime import datetime

from servers.Server import Server
from data_models.Config import (
    ConfigGroup, ConfigItem, ConfigChange, ConfigBackup,
    ConfigGroupCreate, ConfigGroupUpdate, ConfigItemCreate, ConfigItemUpdate,
    ConfigUpdate, ConfigBatchUpdate, ConfigValidationRequest,
    ConfigBackupCreate, ApiResponse, PaginatedResponse, ConfigChangeType,
    ValidationResult
)
from core.config import ConfigManager


logger = logging.getLogger(__name__)


async def check_user_login(request: Request):
    """检查用户是否已登录"""
    if hasattr(request, 'session') and request.session.get('logged_in'):
        return True
    return False


def get_login_redirect():
    """获取登录重定向响应"""
    from fastapi.responses import RedirectResponse
    return RedirectResponse(url='/login', status_code=302)


def get_current_admin_user():
    """获取当前管理员用户（简化版本，实际项目中需要完整的认证逻辑）"""
    return {
        'username': 'admin',
        'ip_address': '127.0.0.1',
        'user_agent': 'ConfigAdmin'
    }


class ConfigServer(Server):
    """配置管理服务器 - 处理配置管理相关功能"""

    def __init__(self):
        super().__init__(log_init=True)
        self.config_manager: Optional[ConfigManager] = None
        self.router = APIRouter(prefix="/admin/config", tags=["配置管理"])

    def _get_config_manager(self) -> ConfigManager:
        """获取配置管理器实例"""
        if not self.config_manager:
            raise HTTPException(status_code=500, detail="Config manager not initialized")
        return self.config_manager

    def setup_config_manager(self, config_manager: ConfigManager):
        """设置配置管理器"""
        self.config_manager = config_manager

    # ==================== 配置分组管理 ====================

    def _setup_group_routes(self):
        """设置配置分组相关路由"""

        @self.router.get("/groups")
        async def get_config_groups():
            """获取配置分组列表"""
            try:
                manager = self._get_config_manager()
                groups = await manager.get_config_groups()

                return {
                    "code": 200,
                    "message": "success",
                    "data": [group.dict() for group in groups],
                    "total": len(groups)
                }
            except Exception as e:
                logger.error(f"Failed to get config groups: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": [],
                    "total": 0
                }

        @self.router.post("/groups", response_model=ApiResponse)
        async def create_config_group(
            group_data: ConfigGroupCreate,
            current_user: dict = Depends(get_current_admin_user)
        ):
            """创建配置分组"""
            try:
                manager = self._get_config_manager()
                group_id = await manager._repository.create_config_group(group_data.dict())

                return ApiResponse(
                    success=True,
                    message=f"配置分组创建成功，ID: {group_id}",
                    data={"id": group_id}
                )
            except Exception as e:
                logger.error(f"Failed to create config group: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.put("/groups/{group_id}", response_model=ApiResponse)
        async def update_config_group(
            group_id: int = Path(..., description="分组ID"),
            group_data: ConfigGroupUpdate = Body(...),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """更新配置分组"""
            try:
                manager = self._get_config_manager()
                success = await manager._repository.update_config_group(group_id, group_data.dict(exclude_unset=True))

                if not success:
                    raise HTTPException(status_code=404, detail="配置分组不存在")

                return ApiResponse(
                    success=True,
                    message="配置分组更新成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to update config group {group_id}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.delete("/groups/{group_id}", response_model=ApiResponse)
        async def delete_config_group(
            group_id: int = Path(..., description="分组ID"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """删除配置分组（软删除）"""
            try:
                manager = self._get_config_manager()
                success = await manager._repository.delete_config_group(group_id)

                if not success:
                    raise HTTPException(status_code=404, detail="配置分组不存在")

                return ApiResponse(
                    success=True,
                    message="配置分组删除成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to delete config group {group_id}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    # ==================== 配置项管理 ====================

    def _setup_item_routes(self):
        """设置配置项相关路由"""

        @self.router.get("/items")
        async def get_config_items(
            group_id: Optional[int] = Query(None, description="分组ID"),
            category: Optional[str] = Query(None, description="配置分类"),
            search: Optional[str] = Query(None, description="搜索关键词"),
            page: int = Query(1, ge=1, description="页码"),
            page_size: int = Query(20, ge=1, le=100, description="每页数量")
        ):
            """获取配置项列表"""
            try:
                manager = self._get_config_manager()
                items, total = await manager._repository.get_config_items(
                    group_id=group_id,
                    category=category,
                    search=search,
                    page=page,
                    page_size=page_size
                )

                return {
                    "code": 200,
                    "message": "success",
                    "data": items,
                    "total": total,
                    "page": page,
                    "page_size": page_size
                }
            except Exception as e:
                logger.error(f"Failed to get config items: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": [],
                    "total": 0,
                    "page": page,
                    "page_size": page_size
                }

        @self.router.get("/items/{key}", response_model=ApiResponse)
        async def get_config_item(
            key: str = Path(..., description="配置键名"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """获取单个配置项详情"""
            try:
                manager = self._get_config_manager()
                config_data = await manager.get_config_with_metadata(key)

                if not config_data['metadata']:
                    raise HTTPException(status_code=404, detail="配置项不存在")

                return ApiResponse(
                    success=True,
                    data=config_data
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to get config item {key}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.put("/items/{key}", response_model=ApiResponse)
        async def update_config_item(
            key: str = Path(..., description="配置键名"),
            request: ConfigUpdate = Body(...),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """更新配置项"""
            try:
                manager = self._get_config_manager()

                # 获取客户端信息
                client_info = {
                    'ip_address': current_user.get('ip_address'),
                    'user_agent': current_user.get('user_agent')
                }

                # 更新配置值
                if request.current_value is not None:
                    success = await manager.update_config(
                        key=key,
                        value=request.current_value,
                        changed_by=current_user.get('username', 'admin'),
                        change_reason=request.__dict__.get('change_reason'),
                        **client_info
                    )

                    if not success:
                        raise HTTPException(status_code=400, detail="配置更新失败")

                # 更新其他元数据
                if any([request.display_name, request.description, request.value_range,
                        request.validation_rule, request.is_sensitive is not None,
                        request.is_reload_required is not None, request.is_readonly is not None]):

                    item_data = request.dict(exclude_unset=True, exclude={'current_value'})
                    metadata = await manager.get_config_metadata(key)
                    if metadata:
                        await manager._repository.update_config_item(metadata['id'], item_data)

                return ApiResponse(
                    success=True,
                    message="配置项更新成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to update config item {key}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.put("/items/batch", response_model=ApiResponse)
        async def batch_update_config_items(
            request: ConfigBatchUpdate = Body(...),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """批量更新配置项"""
            try:
                manager = self._get_config_manager()

                # 获取客户端信息
                client_info = {
                    'ip_address': current_user.get('ip_address'),
                    'user_agent': current_user.get('user_agent')
                }

                # 批量更新
                results = await manager.batch_update_configs(
                    updates=request.updates,
                    changed_by=current_user.get('username', 'admin'),
                    change_reason=request.change_reason,
                    **client_info
                )

                success_count = sum(1 for success in results.values() if success)
                total_count = len(results)

                return ApiResponse(
                    success=True,
                    message=f"批量更新完成：{success_count}/{total_count} 项成功",
                    data=results
                )
            except Exception as e:
                logger.error(f"Failed to batch update config items: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.post("/items", response_model=ApiResponse)
        async def create_config_item(
            item_data: ConfigItemCreate,
            current_user: dict = Depends(get_current_admin_user)
        ):
            """创建配置项"""
            try:
                manager = self._get_config_manager()
                item_id = await manager._repository.create_config_item(item_data.dict())

                # 重载配置缓存
                await manager.reload_config(item_data.key_name)

                return ApiResponse(
                    success=True,
                    message=f"配置项创建成功，ID: {item_id}",
                    data={"id": item_id}
                )
            except Exception as e:
                logger.error(f"Failed to create config item: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.delete("/items/{key}", response_model=ApiResponse)
        async def delete_config_item(
            key: str = Path(..., description="配置键名"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """删除配置项"""
            try:
                manager = self._get_config_manager()

                # 获取配置项
                item = await manager._repository.get_config_item_by_key(key)
                if not item:
                    raise HTTPException(status_code=404, detail="配置项不存在")

                # 删除配置项
                success = await manager._repository.delete_config_item(item['id'])

                if success:
                    # 从缓存中移除
                    async with manager._lock:
                        manager._config_cache.pop(key, None)
                        manager._config_metadata.pop(key, None)

                return ApiResponse(
                    success=True,
                    message="配置项删除成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to delete config item {key}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    # ==================== 配置验证 ====================

    def _setup_validation_routes(self):
        """设置配置验证相关路由"""

        @self.router.post("/validate", response_model=ApiResponse)
        async def validate_config(
            request: ConfigValidationRequest = Body(...),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """验证配置值"""
            try:
                manager = self._get_config_manager()
                result = await manager.validate_config_value(request.key, request.value)

                return ApiResponse(
                    success=True,
                    data=result.dict()
                )
            except Exception as e:
                logger.error(f"Failed to validate config {request.key}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    # ==================== 配置重载和重启 ====================

    def _setup_reload_routes(self):
        """设置配置重载和重启相关路由"""

        @self.router.post("/reload", response_model=ApiResponse)
        async def reload_config(
            key: Optional[str] = Query(None, description="配置键名，不填则重载所有"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """重载配置"""
            try:
                manager = self._get_config_manager()
                success = await manager.reload_config(
                    key=key,
                    changed_by=current_user.get('username', 'admin')
                )

                if not success:
                    raise HTTPException(status_code=500, detail="配置重载失败")

                message = f"配置 {key} 重载成功" if key else "所有配置重载成功"
                return ApiResponse(
                    success=True,
                    message=message
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to reload config: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.post("/restart", response_model=ApiResponse)
        async def restart_service(
            reason: Optional[str] = Query(None, description="重启原因"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """重启服务"""
            try:
                manager = self._get_config_manager()

                # 记录重启操作
                await manager._history_manager.record_service_restart(
                    changed_by=current_user.get('username', 'admin'),
                    reason=reason
                )

                # 通知服务重启
                await manager._notify_service_restart()

                return ApiResponse(
                    success=True,
                    message="服务重启命令已发送，系统将在几秒钟内重启"
                )
            except Exception as e:
                logger.error(f"Failed to restart service: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    # ==================== 配置历史 ====================

    def _setup_history_routes(self):
        """设置配置历史相关路由"""

        @self.router.get("/history")
        async def get_config_history(
            config_key: Optional[str] = Query(None, description="配置键名"),
            change_type: Optional[str] = Query(None, description="变更类型"),
            page: int = Query(1, ge=1, description="页码"),
            page_size: int = Query(20, ge=1, le=100, description="每页数量")
        ):
            """获取配置变更历史"""
            try:
                manager = self._get_config_manager()

                if config_key:
                    history = await manager.get_config_history(config_key, page_size, (page-1)*page_size)
                    total = await manager._history_manager.get_config_history_count(config_key)
                else:
                    # 简化处理，获取所有历史记录
                    history = await manager.get_recent_changes(168)  # 最近一周
                    total = len(history)

                return {
                    "code": 200,
                    "message": "success",
                    "data": history,
                    "total": total,
                    "page": page,
                    "page_size": page_size
                }
            except Exception as e:
                logger.error(f"Failed to get config history: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": [],
                    "total": 0,
                    "page": page,
                    "page_size": page_size
                }

        @self.router.get("/history/recent")
        async def get_recent_changes(
            hours: int = Query(24, ge=1, le=168, description="最近小时数")
        ):
            """获取最近的配置变更"""
            try:
                manager = self._get_config_manager()
                changes = await manager.get_recent_changes(hours)

                return {
                    "code": 200,
                    "message": "success",
                    "data": changes
                }
            except Exception as e:
                logger.error(f"Failed to get recent changes: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": []
                }

    # ==================== 配置备份 ====================

    def _setup_backup_routes(self):
        """设置配置备份相关路由"""

        @self.router.get("/backups")
        async def list_config_backups(
            page: int = Query(1, ge=1, description="页码"),
            page_size: int = Query(20, ge=1, le=100, description="每页数量"),
            include_auto: bool = Query(True, description="是否包含自动备份")
        ):
            """列出配置备份"""
            try:
                manager = self._get_config_manager()
                # 简化分页，只获取所有数据
                backups = await manager.list_backups(limit=1000)  # 获取足够多的数据
                all_backups = backups

                # 简单的客户端分页
                start_index = (page - 1) * page_size
                end_index = start_index + page_size
                paginated_backups = all_backups[start_index:end_index]

                return {
                    "code": 200,
                    "message": "success",
                    "data": paginated_backups,
                    "total": len(all_backups),
                    "page": page,
                    "page_size": page_size
                }
            except Exception as e:
                logger.error(f"Failed to list config backups: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": [],
                    "total": 0,
                    "page": page,
                    "page_size": page_size
                }

        @self.router.post("/backups", response_model=ApiResponse)
        async def create_config_backup(
            request: ConfigBackupCreate = Body(...),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """创建配置备份"""
            try:
                manager = self._get_config_manager()
                backup_id = await manager.create_backup(
                    backup_name=request.backup_name,
                    created_by=current_user.get('username', 'admin'),
                    description=request.backup_description
                )

                return ApiResponse(
                    success=True,
                    message=f"配置备份创建成功，ID: {backup_id}",
                    data={"backup_id": backup_id}
                )
            except Exception as e:
                logger.error(f"Failed to create config backup: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.get("/backups/{backup_id}/restore-plan", response_model=ApiResponse)
        async def get_backup_restore_plan(
            backup_id: int = Path(..., description="备份ID"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """获取备份恢复计划"""
            try:
                manager = self._get_config_manager()
                current_configs = await manager.get_all_configs()
                plan = await manager._backup_manager.get_restore_plan(backup_id, current_configs)

                return ApiResponse(
                    success=True,
                    data=plan
                )
            except Exception as e:
                logger.error(f"Failed to get backup restore plan: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.post("/backups/{backup_id}/restore", response_model=ApiResponse)
        async def restore_config_backup(
            backup_id: int = Path(..., description="备份ID"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """恢复配置备份"""
            try:
                manager = self._get_config_manager()
                success = await manager.restore_backup(
                    backup_id=str(backup_id),
                    created_by=current_user.get('username', 'admin')
                )

                if not success:
                    raise HTTPException(status_code=500, detail="配置恢复失败")

                return ApiResponse(
                    success=True,
                    message="配置备份恢复成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to restore config backup {backup_id}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

        @self.router.delete("/backups/{backup_id}", response_model=ApiResponse)
        async def delete_config_backup(
            backup_id: int = Path(..., description="备份ID"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """删除配置备份"""
            try:
                manager = self._get_config_manager()
                success = await manager._backup_manager.delete_backup(backup_id)

                if not success:
                    raise HTTPException(status_code=404, detail="备份不存在")

                return ApiResponse(
                    success=True,
                    message="配置备份删除成功"
                )
            except HTTPException:
                raise
            except Exception as e:
                logger.error(f"Failed to delete config backup {backup_id}: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    # ==================== 系统状态 ====================

    def _setup_status_routes(self):
        """设置系统状态相关路由"""

        @self.router.get("/status")
        async def get_config_status():
            """获取配置系统状态"""
            try:
                manager = self._get_config_manager()
                status = await manager.get_config_status()

                return {
                    "code": 200,
                    "message": "success",
                    "data": status
                }
            except Exception as e:
                logger.error(f"Failed to get config status: {e}")
                return {
                    "code": 500,
                    "message": str(e),
                    "data": None
                }

        @self.router.get("/export")
        async def export_configs(
            format: str = Query("json", description="导出格式"),
            current_user: dict = Depends(get_current_admin_user)
        ):
            """导出配置"""
            try:
                manager = self._get_config_manager()
                export_data = await manager.export_configs(format)

                # 生成文件名
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                filename = f"any4any_config_{timestamp}.{format}"

                return StreamingResponse(
                    iter([export_data]),
                    media_type="application/json",
                    headers={"Content-Disposition": f"attachment; filename={filename}"}
                )
            except Exception as e:
                logger.error(f"Failed to export configs: {e}")
                raise HTTPException(status_code=500, detail=str(e))

    def setup_routes(self):
        """设置所有路由"""
        self._setup_group_routes()
        self._setup_item_routes()
        self._setup_validation_routes()
        self._setup_reload_routes()
        self._setup_history_routes()
        self._setup_backup_routes()
        self._setup_status_routes()

    def register_routes(self, app: FastAPI):
        """注册配置管理路由到FastAPI应用"""
        config_router = self.get_router()
        app.include_router(config_router)

        # 注册配置管理前端页面路由
        @app.get("/admin/config", response_class=HTMLResponse)
        async def admin_config_page(request: Request):
            """配置管理页面"""
            config_file = os.path.join("static", "admin", "config.html")
            if os.path.exists(config_file):
                with open(config_file, "r", encoding="utf-8") as f:
                    return HTMLResponse(content=f.read())
            else:
                return HTMLResponse(
                    content="<h1>Configuration Management Page Not Found</h1>"
                             "<p>The configuration management interface could not be loaded.</p>",
                    status_code=404
                )

    def get_router(self) -> APIRouter:
        """获取路由器"""
        if not self.router.routes:
            self.setup_routes()
        return self.router